<template>
  <div class="app-container">
    <p>调整速度：<el-slider v-model="SPEED" style="width: 50%" :min="minSpeed" :max="maxSpeed" :marks="marks" @input="onSpeedChanged" /></p>
    <canvas id="canvas" width="902" height="954">
      您的浏览器不支持 HTML5！！！
    </canvas>
  </div>
</template>

<script>
import TictactoeAI from './ai';

export default {
  name: 'Tictactoe',
  data() {
    return {
      minSpeed: 100,
      maxSpeed: 5000,
      marks: { 100: '快', 5000: '慢' },
      // 画布
      canvas: null,
      graphic: null,
      COLORS: [
        'red', 'blue',
      ],
      SIDES: [
        '红方', '蓝方',
      ],
      SYMBOL_SIDES: {
        'O': 0, 'X': 1,
      },
      SYMBOLS: [
        'O', 'X',
      ],

      // 定时器
      interval: null,
      SPEED: 500, // 越小越快

      // 属性
      current_side: 0, // 当前下棋方
      current_map: null // 当前局面
    };
  },
  mounted() {
    this.init();
  },
  beforeDestroy() {
    clearInterval(this.interval);
  },
  methods: {
    // 调整速度
    onSpeedChanged() {
      clearInterval(this.interval);

      this.interval = setInterval(() => { this.update(); }, this.SPEED);
    },
    // 初始化
    init() {
      // 初始化画布
      this.canvas = document.getElementById('canvas');
      this.graphic = this.canvas.getContext('2d');

      this.graphic.fillStyle = 'white';
      this.graphic.fillRect(0, 0, this.canvas.width, this.canvas.height);

      // 初始化本局先手方
      this.current_side = Math.floor(Math.floor(Math.random() * 10000) / 5000);

      // 初始化当前局面
      this.current_map = new Array(3);
      for (let x = 0; x < 3; x++) {
        this.current_map[x] = new Array(3);
        for (let y = 0; y < 3; y++) {
          this.current_map[x][y] = '';
        }
      }

      // 先手方随机找一个位置下棋
      const rndX = Math.floor(Math.random() * 3);
      const rndY = Math.floor(Math.random() * 3);
      this.current_map[rndX][rndY] = this.SYMBOLS[this.current_side];

      // 转换出手方
      this.current_side = 1 - this.current_side;

      this.interval = setInterval(() => { this.update(); }, this.SPEED);

      this.draw_map();
    },
    win(side) {
      clearInterval(this.interval);
      this.$message(`${this.SIDES[side]} 胜利！`);
      this.init();
    },
    draw() {
      clearInterval(this.interval);
      this.$message(`双方和棋！`);
      this.init();
    },
    // 游戏逻辑控制
    game_logic() {
      // AI 下棋子
      const best_pos = TictactoeAI.getBestPos(this.SYMBOLS[this.current_side], this.current_map);
      if (best_pos) {
        this.current_map[best_pos.x][best_pos.y] = this.SYMBOLS[this.current_side];
      }

      // 转换出手方
      this.current_side = 1 - this.current_side;

      // 判断局面情况
      for (let x = 0; x < 3; x++) {
        if (this.current_map[x][0] !== '' && this.current_map[x][0] === this.current_map[x][1] && this.current_map[x][0] === this.current_map[x][2]) {
          return this.win(this.SYMBOL_SIDES[this.current_map[x][0]]);
        }
      }

      for (let y = 0; y < 3; y++) {
        if (this.current_map[0][y] !== '' && this.current_map[0][y] === this.current_map[1][y] && this.current_map[0][y] === this.current_map[2][y]) {
          return this.win(this.SYMBOL_SIDES[this.current_map[0][y]]);
        }
      }

      if (this.current_map[0][0] !== '' && this.current_map[0][0] === this.current_map[1][1] && this.current_map[0][0] === this.current_map[2][2]) {
        return this.win(this.SYMBOL_SIDES[this.current_map[0][0]]);
      } else if (this.current_map[2][0] !== '' && this.current_map[2][0] === this.current_map[1][1] && this.current_map[2][0] === this.current_map[0][2]) {
        return this.win(this.SYMBOL_SIDES[this.current_map[2][0]]);
      }

      if (true) {
        let is_draw = true;
        for (let x = 0; x < 3; x++) {
          for (let y = 0; y < 3; y++) {
            if (this.current_map[x][y] === '') {
              is_draw = false;
              break;
            }
          }

          if (!is_draw) {
            break;
          }
        }

        if (is_draw) {
          return this.draw();
        }
      }
    },
    // 画出局面
    draw_map() {
      // 清空全屏
      this.graphic.clearRect(0, 0, this.canvas.width, this.canvas.height);

      // 当前下棋手方框
      this.graphic.strokeStyle = 'black';
      this.graphic.strokeRect(1, 1, this.canvas.width - 1, 50);

      // 当前下棋手
      const xsf = '当前下棋手：';
      const text_height = 32;
      this.graphic.font = '22px Courier New';
      this.graphic.fillStyle = 'black';
      this.graphic.fillText(xsf, 10, text_height);

      this.graphic.font = '22px Courier New';
      this.graphic.fillStyle = this.COLORS[this.current_side];
      this.graphic.fillText(this.SIDES[this.current_side], this.graphic.measureText(xsf + ' ').width, text_height);

      // 栅格
      this.graphic.beginPath();
      this.graphic.strokeStyle = 'black';
      this.graphic.moveTo(this.canvas.width / 3, 50);
      this.graphic.lineTo(this.canvas.width / 3, this.canvas.height);
      this.graphic.moveTo(this.canvas.width / 3 * 2, 50);
      this.graphic.lineTo(this.canvas.width / 3 * 2, this.canvas.height);
      this.graphic.moveTo(1, (this.canvas.height - 50) / 3 + 50);
      this.graphic.lineTo(this.canvas.width, (this.canvas.height - 50) / 3 + 50);
      this.graphic.moveTo(1, (this.canvas.height - 50) / 3 * 2 + 50);
      this.graphic.lineTo(this.canvas.width, (this.canvas.height - 50) / 3 * 2 + 50);
      this.graphic.stroke();

      // 当前局面
      for (let x = 0; x < 3; x++) {
        for (let y = 0; y < 3; y++) {
          const side = this.SYMBOL_SIDES[this.current_map[x][y]];
          if (!isNaN(side)) {
            this.graphic.beginPath();
            this.graphic.strokeStyle = this.COLORS[side];
            if (this.SYMBOLS[side] === 'O') {
              this.graphic.arc(
                x * this.canvas.width / 3 + this.canvas.width / 6, // 圆心 X
                y * (this.canvas.height - 50) / 3 + (this.canvas.height - 50) / 6 + 50, // 圆心 Y
                this.canvas.width / 6 - 10, // 半径
                0, 2 * Math.PI // 整个圆
              );
            } else if (this.SYMBOLS[side] === 'X') {
              this.graphic.moveTo(x * this.canvas.width / 3 + 10, y * (this.canvas.height - 50) / 3 + 10 + 50); // 左上
              this.graphic.lineTo(x * this.canvas.width / 3 + this.canvas.width / 3 - 20, y * (this.canvas.height - 50) / 3 + (this.canvas.height - 50) / 3 - 10 + 50); // 右下
              this.graphic.moveTo(x * this.canvas.width / 3 + this.canvas.width / 3 - 20, y * (this.canvas.height - 50) / 3 + 10 + 50); // 右上
              this.graphic.lineTo(x * this.canvas.width / 3 + 10, y * (this.canvas.height - 50) / 3 + (this.canvas.height - 50) / 3 - 10 + 50); // 左下
            }
            this.graphic.stroke();
          }
        }
      }
    },
    // 定时刷新画面
    update() {
      this.game_logic();
      this.draw_map();
    }
  }
};
</script>
